<?php
/**
 * 责任链模式: 将请求的发送和接收解耦，让多个接收对象都有机会处理这个请求。将这些接收对象串成一条链，并沿着这条链传递这个请求，直到链上的某个接收对象能够处理它为止。
 */

/**
 * 词汇过滤链条
 */
abstract class FilterChain {
    protected $next;

    public function setNext($next) {
        $this->next = $next;
    }

    abstract public function filter($message);
}

/**
 * 链条第一步:非法内容拦截
 */
class FilterStrict extends FilterChain {
    public function filter($message) {
        try {
            foreach (['黄X', '赌X', '毒X'] as $v) {
                if (strpos($message, $v) !== false) {
                    throw new \Exception('信息包含敏感词汇,已被禁止发布!');
                }
            }
            if ($this->next) {
                return $this->next->filter($message);
            } else {
                return $message;
            }
        } catch (\Exception $e) {
            return $e->getMessage();
        }
    }
}

/**
 * 链条第二步:特殊关键词过滤替换
 */
class FilterWarning extends FilterChain {
    public function filter($message) {
        $message = str_replace(['打架', '斗殴', '暴力'], '*', $message);
        if ($this->next) {
            return $this->next->filter($message);
        } else {
            return $message;
        }
    }
}

/**
 * 链条第三步: 检测如果包含手机号,则中间4位替换为*号
 */
class FilterMobile extends FilterChain {
    public function filter($message) {
        $message = preg_replace("/(1[3|5|7|8]\d)\d{4}(\d{4})/i", "$1****$2", $message);
        if ($this->next) {
            return $this->next->filter($message);
        } else {
            return $message;
        }
    }
}

$f1 = new FilterStrict();
$f2 = new FilterWarning();
$f3 = new FilterMobile();

$f1->setNext($f2);
$f2->setNext($f3);

//测试正常评论内容过滤关键词
//输出: 这是一条正常的评论，需要替换掉*和*这种词，然后给手机号加上星：133****3333，然后才可以对外展示
$comment_content1 = "这是一条正常的评论，需要替换掉打架和斗殴这种词，然后给手机号加上星：13333333333，然后才可以对外展示";
echo $f1->filter($comment_content1) . PHP_EOL;

//测试非法评论内容
//输出: 信息包含敏感词汇,已被禁止发布!
$comment_content2 = "这是一条非法的评论，因为包含了毒X，直接被拦截了";
echo $f1->filter($comment_content2) . PHP_EOL;
